package com.hexanet.server.resources;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

import com.hexanet.bom.Player;
import com.hexanet.bom.Role;
import com.hexanet.server.dao.PlayerDao;
import com.hexanet.server.dao.RoleDao;
import com.hexanet.server.reader.HexanetReader;

import flexjson.JSONSerializer;
import flexjson.transformer.IterableTransformer;

@Path("/players")
public class PlayerResource {

    PlayerDao playerDao = new PlayerDao();
    RoleDao roleDao = new RoleDao();

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/login")
    public Response loginPlayer(@Context SecurityContext sc,
	    InputStream inputStream) {

	HexanetReader<Player> reader = new HexanetReader<Player>();
	Player p = reader.getDeserializedObject(inputStream);

	Player loggedInPlayer = playerDao.login(p.getMail(),
		DigestUtils.shaHex(p.getPasswordSha1()));
	

	if (loggedInPlayer == null) {
	    return Response.serverError().build();
	}
	
	System.out.println("server size " + loggedInPlayer.getOwningCells().size());

	// .include("owningCells.servers")
	JSONSerializer serializer = new JSONSerializer();
	String json = serializer.exclude("passwordSha1")
		.include("owningCells")
		.include("owningCells.servers")
		.include("owningCells.firewall")
		.transform(new IterableTransformer(), Collection.class)
		.serialize(loggedInPlayer);

	return Response.ok(json, MediaType.APPLICATION_JSON).build();

    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{id}")
    public Response getPlayerById(@Context SecurityContext sc,
	    @PathParam("id") Long id) {

	System.out.println("loading player with id " + id);
	Player p = playerDao.load(id);
	System.out.println(p.getNickname());
	
	JSONSerializer serializer = new JSONSerializer();
	String json = serializer.exclude("passwordSha1").exclude("owningCells")
		.transform(new IterableTransformer(), Collection.class)
		.serialize(p);

	return Response.ok(json, MediaType.APPLICATION_JSON).build();

    }

  
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/create")
    public Response createPlayer(InputStream inputStream) {
	HexanetReader<Player> reader = new HexanetReader<Player>();
	Player p = reader.getDeserializedObject(inputStream);

	if (p.getMail() == null
		|| p.getMail().isEmpty()
		|| p.getPasswordSha1() == null
		|| p.getPasswordSha1().isEmpty()
		|| !p.getPasswordSha1().equalsIgnoreCase(
			p.getPasswordSha1Repeat())) {
	    System.out
		    .println("Mail and password are mandatory and passwords have to be equal");
	    return Response.serverError().build();
	}

	if (playerDao.playerExists(p.getMail())) {
	    System.out.println("Mail already exists in system");
	    return Response.serverError().build();
	}
	
	p.setPasswordSha1(DigestUtils.shaHex(p.getPasswordSha1()));

	playerDao.save(p);
	
	Role loggedinRole = new Role();
	loggedinRole.setMail(p.getMail());
	loggedinRole.setName("loggedin");
	
	roleDao.save(loggedinRole);
	
	System.out.println("added player = " + p.getNickname());
	return Response.ok().build();
    }
    
    
    @DELETE
    @Path("/remove/{id}")
    public Response removePlayer(@Context SecurityContext sc,
	    @PathParam("id") Long id)
    {
	String name = sc.getUserPrincipal().getName();
	
	Player loggedInPlayer = playerDao.getByPrincipal(name);
	
	System.out.println(loggedInPlayer.getId().intValue());
	System.out.println(id.intValue());
	// a logged in player can only delte himself
	if(loggedInPlayer.getId().intValue() == id.intValue())
	{
	    System.out.println("starting delete");
	    roleDao.removeRoleForPrincipal(loggedInPlayer.getMail());
	    playerDao.delete(loggedInPlayer);
	    return Response.ok().build();
	}
	System.out.println("after delete");
	
	return Response.serverError().build();
	
    }
    
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/save")
    public Response savePlayer(@Context SecurityContext sc,
	    InputStream inputStream)
    {
	HexanetReader<Player> reader = new HexanetReader<Player>();
	Player newPlayer = reader.getDeserializedObject(inputStream);

	Player savePlayer = playerDao.merge(newPlayer);
	
	if(!newPlayer.getNickname().equals(newPlayer.getNickname()))
	{
	    savePlayer.setNickname(newPlayer.getNickname());
	}
	
	playerDao.save(savePlayer);
	
	System.out.println("saved player = " + savePlayer.getNickname());
	return Response.ok().build();
    }
    
    

}
